import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;


public class Process {
	int processId;
	String processName;
	int arrivalTime;
	int[] cpuAndIOTimes;
	int operationCounter;
	int waitTime;
	
	boolean finished = false;
	boolean ioMode = false;
	
	Process(int pid, String name, int arrival, int[] cpuIOList)
	{
		waitTime = 0;
		processId = pid;
		processName = name;
		arrivalTime = arrival;
		cpuAndIOTimes = cpuIOList;
		ResetProcessState();
	}
	
	void ResetProcessState()
	{
		operationCounter = 0;
		finished = false;
		ioMode = false;	
	}
	
	
	void RunForOneTick()
	{
		if (cpuAndIOTimes[operationCounter] > 0)
		{
			cpuAndIOTimes[operationCounter]--;
		} else {
			System.out.println("You cant run me! i need to switch modes (io or cpu)");
		}

	}
	
	void NextOperation()
	{
		operationCounter++;
		IsFinished(); //when getting the value for is finished, it recalculates it and updates the finished variable
	}
	
	boolean NeedsIO()
	{
		if (!InIO() && !IsFinished() && getCurrentOperationTime() == 0)
			return true;
		return false;
	}
	
	boolean DoneWithIO()
	{
		if (!InIO() && !IsFinished() && getCurrentOperationTime() == 0)
			return true;
		return false;
	}
	
	boolean InIO()
	{
		return ioMode;
		
	}
	
	boolean IsFinished()
	{
		if (!finished)
		{
			if (operationCounter == cpuAndIOTimes.length && getCurrentOperationTime() == 0)
			{
				finished = true;
			}
		}
		return finished;
	}
	
	static public ArrayList<Process> LoadProcesses(String file) throws FileNotFoundException
	{
		ArrayList<Process> loadedProcesses = new ArrayList<Process>();
		File f = new File(file);
		Scanner fileScanner = new Scanner(f);
		while (fileScanner.hasNextLine())
		{
			String line = fileScanner.nextLine();
			String[] parts = line.split(" ");
			int[] cpuio = new int[parts.length - 3];
			for (int i =3; i < parts.length; i++)
			{
				cpuio[i-3] = Integer.parseInt(parts[i]);
			}
			Process p = new Process(Integer.parseInt(parts[0]), parts[1], Integer.parseInt(parts[2]), cpuio);
			loadedProcesses.add(p);
		}
		return loadedProcesses;
	}
	
	static public void ResetProcessList(ArrayList<Process> list)
	{
		for(Process p : list)
		{
			p.ResetProcessState();
		}
	}
	
	static public boolean ProcessesInListFinished(ArrayList<Process> list)
	{
		for (Process p : list)
		{
			if (!p.IsFinished())
				return false;
		}
		return true;
	}
	
	public int getArrivalTime()
	{
		return arrivalTime;
	}
	
	private int getCurrentOperationTime()
	{
		return cpuAndIOTimes[operationCounter];
	}

	public int getWaitTime() {
		return waitTime;
	}
	
}
